package com.xj.util;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static java.util.Calendar.*;

/**
 * @Description: 日期工具类
 * @Author: Chuanlei.Sun
 * @Date: Created in 2018/10/28 2:15
 */
@Slf4j
public final class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    public static final String yyyy_MM_dd = "yyyy-MM-dd";
	public static final String yyyyMMdd_china = "yyyy年MM月dd日";
    public static final String HH_mm_ss = "HH:mm:ss";
    public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String HHmmss = "HHmmss";
    public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss";
    public static final String HHmmssSSS = "HHmmssSSS";
    public static final String yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS";
    public static final String DATE_FULL = "yyyy-MM-dd HH:mm:ss";
	public static final String YYYY_MM_DD_PATH = "yyyy/MM/dd";
    private static String[] parsePatterns = {
            "yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss", "yyyyMMddHHmmss",
            "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm", "yyyyMMddHHmm",
            "yyyy/MM/dd", "yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd",
            "yyyy.MM", "yyyy-MM", "yyyy/MM", "yyyyMM"
    };

    /**
     * 获取当前日期字符串 格式（yyyy-MM-dd）
     *
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:34
     */
    public static String getDate() {
        return formatDate(new Date(), yyyy_MM_dd);
    }

    public static String getDate(Date d, String format) {
        return formatDate(d, format);
    }
    /**
     * 获取当前时间字符串 格式（HH:mm:ss）
     *
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:34
     */
    public static String getTime() {
        return formatDate(new Date(), HH_mm_ss);
    }

    /**
     * 获取当前时间全格式字符串 格式（yyyyMMddHHmmssSSS）
     *
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:34
     */
    public static String getTimeStamp() {
        return formatDate(new Date(), yyyyMMddHHmmssSSS);
    }

    /**
     * 获取当前时间指定格式的日期字符串
     *
     * @param pattern 指定格式
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:29
     */
    public static String formatDate(String pattern) {
        return formatDate(new Date(), pattern);
    }

    /**
     * 获取指定日期 指定格式的 日期字符串
     *
     * @param date    指定日期
     * @param pattern 指定格式
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:31
     */
    public static String formatDate(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 格式化日期字符串
     *
     * @param str 日期字符串
     * @return java.util.Date
     * @author Chuanlei.Sun
     * @date 2018/10/28 22:45
     */
    public static Date parseDate(String str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str, parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 校验开始日期与结束日期是否合法
     *
     * @param beginDate 开始日期
     * @param endDate   结束日期
     * @param pattern   日期格式
     * @return boolean
     * @author Chuanlei.Sun
     * @date 2018/10/30 13:36
     */
    public static boolean orderIsTrue(String beginDate, String endDate, String pattern) {
        if (StringUtils.isAnyBlank(beginDate, endDate, pattern)) {
            return false;
        }
        try {
            Date dateForm = parseDate(beginDate, pattern);
            Date dateTo = parseDate(endDate, pattern);
            return dateForm.compareTo(dateTo) <= 0;
        } catch (Exception e) {
            log.error("日期格式化异常：", e);
            return false;
        }
    }

    /**
     * 校验日期字符串格式
     *
     * @param dateStr 日期字符串
     * @param pattern 指定格式
     * @return boolean
     * @author Chuanlei.Sun
     * @date 2018/11/17 16:06
     */
    public static boolean checkFormat(String dateStr, String pattern) {
        try {
            parseDate(dateStr, pattern);
            return true;
        } catch (Exception e) {
            log.error("日期格式化异常：", e);
            return false;
        }
    }

    /**
     * 获取当前网络时间
     *
     * @param webUrl 请求地址
     * @param format 日期格式
     * @return java.lang.String
     * @author Chuanlei.Sun
     * @date 2019/5/8 13:44
     */
    public static String getNetTime(String webUrl, String format) {
        String netTime = "";
        try {
            log.info(">>>>>>>>> 获取地址:{}的时间开始,格式:{}", webUrl, format);
            URL url = new URL(webUrl);
            URLConnection conn = url.openConnection();
            conn.connect();
            long dateL = conn.getDate();
            Date date = new Date(dateL);
            SimpleDateFormat dateFormat = new SimpleDateFormat(format);
            netTime = dateFormat.format(date);
            log.info(">>>>>>>>> {}的时间:{}", webUrl, netTime);
        } catch (IOException e) {
            log.warn(">>>>>>>>> 获取{}的时间异常,{}", webUrl, e);
        } finally {
            return netTime;
        }
    }




	public static String getAddDate(String format,int  day) {
		Calendar d = Calendar.getInstance();
		d.setTime(new Date());
		d.add(DAY_OF_MONTH, day);
		String startDate = DateUtils.formatDate(d.getTime(), format);
		return startDate;
	}

	public static String getStartDate(String format,String closeDay) {
		Calendar d = Calendar.getInstance();
		d.setTime(new Date());
		int day = d.get(Calendar.DAY_OF_MONTH);
		if (day < Integer.valueOf(closeDay)){
			d.add(Calendar.MONTH, -1);
		}
		d.set(Calendar.DAY_OF_MONTH, 1);
		d.set(Calendar.HOUR_OF_DAY,0);
		d.set(Calendar.MINUTE,0);
		d.set(Calendar.SECOND,0);
		d.set(Calendar.MILLISECOND,0);
		String startDate = DateUtils.formatDate(d.getTime(), format);
		return startDate;
	}

    public static Date getLastest(Date date) {
         return parseTime(date, 23, 59, 59, 999);
    }


    public static Date parseTime(Date date, int hourOfDay, int minute,
                                 int second, int milliSecond) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        setCalendarTime(cal, hourOfDay, minute, second, milliSecond);
        return cal.getTime();
    }

    private static void setCalendarTime(Calendar cal, int hourOfDay,
                                        int minute, int second, int milliSecond) {
        cal.set(HOUR_OF_DAY, hourOfDay);
        cal.set(MINUTE, minute);
        cal.set(SECOND, second);
        cal.set(MILLISECOND, milliSecond);
    }

    public static Date parseDate(String datetime, String formatPattern) {
        if (formatPattern == null) {
        	formatPattern = DATE_FULL;
        }

        SimpleDateFormat format = new SimpleDateFormat(formatPattern);
        try {
            return format.parse(datetime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public  static  Date  getLastDayofMonth(Date  ddate){
	    Calendar  calendar=Calendar.getInstance();
	    calendar.setTime(ddate);
	    int  year=calendar.get(Calendar.YEAR);
	    int month=calendar.get(Calendar.MONTH)+1;
	    int  day=1;
	    calendar.set(year,month,1);
	    calendar.add(Calendar.DAY_OF_MONTH,-1);
	    Date  d=calendar.getTime();
	    return  d;
    }

    public  static  String   getLastDayofBeforeMonth(Date  ddate,String  pattern){
        Calendar  calendar=Calendar.getInstance();
        calendar.setTime(ddate);
        int  year=calendar.get(Calendar.YEAR);
        int month=calendar.get(Calendar.MONTH);
        int  day=1;
        calendar.set(year,month,1);
        calendar.add(Calendar.DAY_OF_MONTH,-1);
        Date  d=calendar.getTime();
        return   DateUtils.formatDate(d,DateUtils.yyyy_MM_dd);
    }

	/**
	 * 根据关账日获取开始日期
	 * @param closeDay
	 * @return LocalDate
	 */
	public static LocalDate getBeginDateByCloseDay(String closeDay){
    	LocalDate now = LocalDate.now();
    	LocalDate beginDate = now.with(TemporalAdjusters.firstDayOfMonth());
    	if(now.getDayOfMonth() < Integer.valueOf(closeDay).intValue() ){
		    beginDate = beginDate.minusMonths(1);
	    }
	    return beginDate;
    }

	/**
	 * 根据关账日获取开始日期
	 * @param closeDay
	 * @param pattern 返回日期字符串格式
	 * @return String
	 */
	public static String getBeginDateByCloseDay(String closeDay,String pattern){
		DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
		LocalDate now = LocalDate.now();
		LocalDate beginDate = now.with(TemporalAdjusters.firstDayOfMonth());
		if(now.getDayOfMonth() < Integer.valueOf(closeDay).intValue() ){
			beginDate = beginDate.minusMonths(1);
		}
		return beginDate.format(format);
	}

	public static String now(String pattern){
		DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
		LocalDateTime now = LocalDateTime.now();
		return now.format(format);
	}

	/**
	 * 获取开始日期，结束日期之前的所有月份的开始日期，结束日期
	 * @param begin
	 * @param end
	 * @return
	 */
	public static List<LocalDate[]> getMonthList(LocalDate begin, LocalDate end) {
		List<LocalDate[]> list = new ArrayList<>();
		while (!(begin.getYear() == end.getYear() && begin.getMonthValue() > end.getMonthValue())) {
			LocalDate firstDayofMonth = begin.with(TemporalAdjusters.firstDayOfMonth());
			LocalDate lastDayofMonth = begin.with(TemporalAdjusters.lastDayOfMonth());
			if (lastDayofMonth.compareTo(end) > 0) {
				lastDayofMonth = end;
			}
			list.add(new LocalDate[]{firstDayofMonth, lastDayofMonth});
			begin = begin.plusMonths(1);
		}
		return list;
	}

	/**
	 * 计算begin到end之前所有月份
	 * @param begin
	 * @param end
	 * @param format
	 * @param resultFormat
	 * @return
	 */
	public static List<String> getYearMonthList(String begin,String end,String format,String resultFormat) {
		List<String> resultList = new ArrayList<>();
		DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
		DateTimeFormatter rdf = DateTimeFormatter.ofPattern(resultFormat);
		LocalDate beginDate = LocalDate.parse(begin, df);
		LocalDate endDate = LocalDate.parse(end, df);
		List<LocalDate[]> list = getMonthList(beginDate, endDate);
		for (int i = 0; i < list.size(); i++) {
			resultList.add(list.get(i)[0].format(rdf));
		}
		return resultList;
	}

	/**
	 * 计算日期字符串begin之后的日期
	 * @param begin
	 * @param format
	 * @param daysToAdd
	 * @return
	 */
	public static String plusDays(String begin,String format,long daysToAdd){
		DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
		LocalDate beginDate = LocalDate.parse(begin, df);
		beginDate = beginDate.plusDays(daysToAdd);
		return beginDate.format(df);
	}

	/**
	 * 根据CrawlerConfigVo的台账开始结束日期，及关账日，获取历史库存日期List
	 * @param crawlerConfigVo
	 * @return
	 */


	/**
	 * 获取开始日期，结束日期之前的所有月份的开始日期，结束日期 格式 yyyy-MM-dd
	 * @param begin
	 * @param end
	 * @return
	 */
	public static List<String[]> getMonthList(String begin,String end) {
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DateUtils.yyyy_MM_dd);
		LocalDate beginDate = LocalDate.parse(begin,dateTimeFormatter);
		LocalDate endDate = LocalDate.parse(end,dateTimeFormatter);
		List<LocalDate[]> list = getMonthList(beginDate,endDate);
		List<String[]> monthList = new ArrayList<>();
		for(LocalDate[] month:list){
			monthList.add(new String[]{month[0].format(dateTimeFormatter),month[1].format(dateTimeFormatter)});
		}
		return monthList;
	}


}
